﻿using System.Collections.Generic;
using System.Linq;
using GammaJul.ReSharper.GammaXaml.Psi.Xaml;
using JetBrains.Application.DataContext;
using JetBrains.ReSharper.Feature.Services.ContextNavigation.ContextSearches;
using JetBrains.ReSharper.Feature.Services.ContextNavigation.ContextSearches.BaseSearches;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Services;
using JetBrains.Util;

namespace GammaJul.ReSharper.GammaXaml.Services.Xaml.Navigation {

	/// <summary>
	/// A custom context search that provides original declarations from a <see cref="CaliburnBoundXamlReference"/>.
	/// Without this context search, the default R# behavior when using "Find Usages" is to provide only the reference,
	/// which, in this case, is the referenced method, thus blocking the possibility to see the field.
	/// </summary>
	[FeaturePart]
	public class CaliburnUsageContextSearch : UsagesContextSearchBase, IFindUsagesContextSearch {
		
		protected override ICollection<DeclaredElementInstance> GetCandidateInstances(IDataContext context, ReferencePreferenceKind kind) {
			ICollection<IReference> references = context.GetData(JetBrains.ReSharper.Psi.Services.DataConstants.REFERENCES);
			if (references == null)
				return EmptyArray<DeclaredElementInstance>.Instance;

			var caliburnReferences = references.OfType<CaliburnBoundXamlReference>().ToArray();
			if (caliburnReferences.Length == 0)
				return EmptyArray<DeclaredElementInstance>.Instance;

			IClrDeclaredElement declElement = context.GetData(JetBrains.ReSharper.Psi.Services.DataConstants.TYPE_OR_TYPE_MEMBER);
			if (declElement == null)
				return EmptyList<DeclaredElementInstance>.InstanceList;

			return new List<DeclaredElementInstance>(1) {
				new DeclaredElementInstance(declElement)
			};
		}

	}

}